/**
* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/

/*!
 * \file kernel_operator_vec_vconv_impl.h
 * \brief
 */
#ifndef ASCENDC_MODULE_OPERATOR_VEC_VCONV_IMPL_H
#define ASCENDC_MODULE_OPERATOR_VEC_VCONV_IMPL_H
#include "kernel_utils.h"
#include "kernel_struct_binary.h"
#include "kernel_struct_unary.h"
#include "kernel_struct_vdeq.h"

namespace AscendC {
__aicore__ inline void CastIntrinsicsImpl(__ubuf__ half* dst, __ubuf__ int32_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    vconv_deq(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride, repeatParams.dstRepStride,
        repeatParams.srcRepStride);
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ half* dst, __ubuf__ int8_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    if (roundMode == RoundMode::CAST_NONE) {
        vconv_s82f16(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
    } else {
        ASCENDC_ASSERT(false, {
            KERNEL_LOG(KERNEL_ERROR,
                "Current RoundMode of Cast from int8_t to half is not supported on current device, only "
                "RoundMode::CAST_NONE support!");});
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ half* dst, __ubuf__ uint8_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    if (roundMode == RoundMode::CAST_NONE) {
        vconv_u82f16(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
    } else {
        ASCENDC_ASSERT(false, {
            KERNEL_LOG(KERNEL_ERROR,
                "Current RoundMode of Cast from uint8_t to half is not supported on current device, only "
                "RoundMode::CAST_NONE support!");});
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ float* dst, __ubuf__ int32_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    if (roundMode == RoundMode::CAST_NONE) {
        vconv_s322f32(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
    } else {
        ASCENDC_ASSERT(false, {
            KERNEL_LOG(KERNEL_ERROR,
                "Current RoundMode of Cast from int32_t to float is not supported on current device, only "
                "RoundMode::CAST_NONE support!");});
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ float* dst, __ubuf__ half* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    if (roundMode == RoundMode::CAST_NONE) {
        vconv_f162f32(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
    } else {
        ASCENDC_ASSERT(false, {
            KERNEL_LOG(KERNEL_ERROR,
                "Current RoundMode of Cast from half to float is not supported on current device, only "
                "RoundMode::CAST_NONE support!");});
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ int32_t* dst, __ubuf__ half* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    switch (roundMode) {
        case RoundMode::CAST_RINT:
            vconv_f162s32r(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_FLOOR:
            vconv_f162s32f(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_CEIL:
            vconv_f162s32c(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_ROUND:
            vconv_f162s32a(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_TRUNC:
            vconv_f162s32z(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_ODD:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_ODD of Cast from half to int32_t is not supported on current device!");
            });
            break;
        case RoundMode::CAST_NONE:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_NONE of Cast from half to int32_t is not supported on current device!");
            });
            break;
        default:
            ASCENDC_ASSERT(false, { KERNEL_LOG(KERNEL_ERROR, "Cast: An invalid RoundMode!"); });
            break;
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ int8_t* dst, __ubuf__ half* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    switch (roundMode) {
        case RoundMode::CAST_FLOOR:
            vconv_f162s8f(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_CEIL:
            vconv_f162s8c(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_ROUND:
            vconv_f162s8a(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_TRUNC:
            vconv_f162s8z(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_NONE:
            vconv_f162s8(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_ODD:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_ODD of Cast from half to int8_t is not supported on current device!");
            });
            break;
        case RoundMode::CAST_RINT:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_RINT of Cast from half to int8_t is not supported on current device!");
            });
            break;
        default:
            ASCENDC_ASSERT(false, { KERNEL_LOG(KERNEL_ERROR, "Cast: An invalid RoundMode!"); });
            break;
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ uint8_t* dst, __ubuf__ half* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    switch (roundMode) {
        case RoundMode::CAST_RINT:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_RINT of Cast from half to uint8_t is not supported on current device!");
            });
            break;
        case RoundMode::CAST_FLOOR:
            vconv_f162u8f(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_CEIL:
            vconv_f162u8c(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_ROUND:
            vconv_f162u8a(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_TRUNC:
            vconv_f162u8z(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_NONE:
            vconv_f162u8(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_ODD:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_ODD of Cast from half to uint8_t is not supported on current device!");
            });
            break;
        default:
            ASCENDC_ASSERT(false, { KERNEL_LOG(KERNEL_ERROR, "Cast: An invalid RoundMode!"); });
            break;
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ half* dst, __ubuf__ float* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    switch (roundMode) {
        case RoundMode::CAST_ODD:
            vconv_f322f16o(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_NONE:
            vconv_f322f16(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_RINT:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_RINT of Cast from float to half is not supported on current device!");
            });
            break;
        case RoundMode::CAST_FLOOR:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_FLOOR of Cast from float to half is not supported on current device!");
            });
            break;
        case RoundMode::CAST_CEIL:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_CEIL of Cast from float to half is not supported on current device!");
            });
            break;
        case RoundMode::CAST_ROUND:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_ROUND of Cast from float to half is not supported on current device!");
            });
            break;
        case RoundMode::CAST_TRUNC:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_TRUNC of Cast from float to half is not supported on current device!");
            });
            break;
        default:
            ASCENDC_ASSERT(false, { KERNEL_LOG(KERNEL_ERROR, "Cast: An invalid RoundMode!"); });
            break;
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ int32_t* dst, __ubuf__ float* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    switch (roundMode) {
        case RoundMode::CAST_RINT:
            vconv_f322s32r(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_FLOOR:
            vconv_f322s32f(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_CEIL:
            vconv_f322s32c(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_ROUND:
            vconv_f322s32a(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_TRUNC:
            vconv_f322s32z(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride);
            break;
        case RoundMode::CAST_ODD:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_ODD of Cast from float to int32_t is not supported on current device!");
            });
            break;
        case RoundMode::CAST_NONE:
            ASCENDC_ASSERT(false, {
                KERNEL_LOG(KERNEL_ERROR,
                    "RoundMode::CAST_NONE of Cast from float to int32_t is not supported on current device!");
            });
            break;
        default:
            ASCENDC_ASSERT(false, { KERNEL_LOG(KERNEL_ERROR, "Cast: An invalid RoundMode!"); });
            break;
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ int16_t* dst, __ubuf__ half* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    if (roundMode == RoundMode::CAST_RINT) {
        vconv_f162s16r(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride, repeatParams.repeatStrideMode,
                repeatParams.strideSizeMode);
    } else {
        ASCENDC_ASSERT(false, {
            KERNEL_LOG(KERNEL_ERROR,
                "Current RoundMode of Cast from half to int16_t is not supported on current device, only "
                "RoundMode::CAST_NONE "
                "support!");
        });
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ uint8_t* dst, __ubuf__ int16_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    ASCENDC_REPORT_NOT_SUPPORT(false, "Cast from type int16_t to uint8_t");
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ int8_t* dst, __ubuf__ int16_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    ASCENDC_REPORT_NOT_SUPPORT(false, "Cast from type int16_t to int8_t");
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ half* dst, __ubuf__ int16_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    if (roundMode == RoundMode::CAST_NONE) {
        vconv_s162f16(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride, repeatParams.repeatStrideMode,
                repeatParams.strideSizeMode);
    } else {
        ASCENDC_ASSERT(false, {
            KERNEL_LOG(KERNEL_ERROR,
                "Current RoundMode of Cast from int16_t to half is not supported on current device, only "
                "RoundMode::CAST_NONE "
                "support!");
        });
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ float* dst, __ubuf__ float* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    ASCENDC_REPORT_NOT_SUPPORT(false, "Cast from type float to float");
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ int64_t* dst, __ubuf__ float* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    ASCENDC_REPORT_NOT_SUPPORT(false, "Cast from type float to int64_t");
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ int16_t* dst, __ubuf__ float* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    ASCENDC_REPORT_NOT_SUPPORT(false, "Cast from type float to int16_t");
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ float* dst, __ubuf__ int16_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    ASCENDC_REPORT_NOT_SUPPORT(false, "Cast from type int16_t to float");
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ int64_t* dst, __ubuf__ int32_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    ASCENDC_REPORT_NOT_SUPPORT(false, "Cast from type int32_t to int64_t");
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ float* dst, __ubuf__ int64_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    ASCENDC_REPORT_NOT_SUPPORT(false, "Cast from type int64_t to float");
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ int32_t* dst, __ubuf__ int64_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    ASCENDC_REPORT_NOT_SUPPORT(false, "Cast from type int64_t to int32_t");
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ int4b_t* dst, __ubuf__ half* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    if (roundMode == RoundMode::CAST_NONE) {
        vconv_f162s4(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride, repeatParams.repeatStrideMode,
                repeatParams.strideSizeMode);
    } else {
        ASCENDC_ASSERT(false, {
            KERNEL_LOG(KERNEL_ERROR,
                "Current RoundMode of Cast from half to int4b_t is not supported on current device, only "
                "RoundMode::CAST_NONE support!");});
    }
}

__aicore__ inline void CastIntrinsicsImpl(__ubuf__ int16_t* dst, __ubuf__ int32_t* src, const RoundMode& roundMode,
    uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    if (roundMode == RoundMode::CAST_NONE) {
        vcbd_s322s16(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
                repeatParams.dstRepStride, repeatParams.srcRepStride, repeatParams.repeatStrideMode,
                repeatParams.strideSizeMode);
    } else {
        ASCENDC_ASSERT(false, {
            KERNEL_LOG(KERNEL_ERROR,
                "Current RoundMode of Cast from int32_t to int16_t is not supported on current device, only "
                "RoundMode::CAST_NONE support!");});
    }
}

// check Cast datatype
template <typename T, typename U>
__aicore__ static inline void CheckCastDatatype() {
    ASCENDC_ASSERT((SupportType<Tuple<T, U>, Tuple<int32_t, half>, Tuple<int16_t, half>, Tuple<float, half>,
        Tuple<int8_t, half>, Tuple<uint8_t, half>, Tuple<int4b_t, half>, Tuple<float, float>, Tuple<int32_t, float>,
        Tuple<half, float>, Tuple<int64_t, float>, Tuple<int16_t, float>, Tuple<half, uint8_t>, Tuple<half, int8_t>,
        Tuple<half, int16_t>, Tuple<float, int16_t>, Tuple<float, int32_t>, Tuple<int16_t, int32_t>,
        Tuple<int64_t, int32_t>, Tuple<half, int32_t>, Tuple<int32_t, int64_t>, Tuple<float, int64_t>>()), {
        KERNEL_LOG(KERNEL_ERROR,
        "Failed to check dtype in Cast, current api support dtype combination is src: half, dst: int32_t / int16_t / "
        "float / int8_t / uint8_t / int4b_t; src: float, dst: int32_t / half; src: uint8_t, dst: half; src: int 8_t, "
        "dst: half; src: int16_t, dst: half; src: int32_t, dst: float / half");});
}

// Cast::Level 2
template <typename T, typename U>
__aicore__ inline void CastImpl(__ubuf__ T* dst, __ubuf__ U* src, const RoundMode& roundMode,
    const uint32_t count)
{
    CheckCastDatatype<T, U>();
    struct UnaryRepeatParams repeatParams;
    if (sizeof(T) < sizeof(U)) {
        if constexpr (IsSameType<T, int4b_t>::value) {
            repeatParams.dstRepStride /= (HALF_FACTOR * HALF_FACTOR);
        } else {
            repeatParams.dstRepStride /= HALF_FACTOR;
        }
    } else if (sizeof(T) > sizeof(U)) {
        repeatParams.srcRepStride /= 2;
    }
    SetMaskCount();
    SetVectorMask<U, MaskMode::COUNTER>(0, count);
    CastIntrinsicsImpl(dst, src, roundMode, 1, repeatParams);
    SetMaskNorm();
    ResetMask();
}

// Cast::Level 0 - mask bit mode
template <typename T, typename U, bool isSetMask = true>
__aicore__ inline void CastImpl(__ubuf__ T* dst, __ubuf__ U* src, const RoundMode& roundMode,
    const uint64_t mask[], uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    CheckCastDatatype<T, U>();
    if constexpr (isSetMask) {
        if (sizeof(T) >= sizeof(U)) {
            AscendCUtils::SetMask<U>(mask[1], mask[0]);
        } else {
            AscendCUtils::SetMask<T>(mask[1], mask[0]);
        }
    }
    CastIntrinsicsImpl(dst, src, roundMode, repeatTime, repeatParams);
}

// Cast::Level 0 - mask count mode
template <typename T, typename U, bool isSetMask = true>
__aicore__ inline void CastImpl(__ubuf__ T* dst, __ubuf__ U* src, const RoundMode& roundMode,
    const uint64_t mask, uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    CheckCastDatatype<T, U>();
    if constexpr (isSetMask) {
        if (sizeof(T) >= sizeof(U)) {
            AscendCUtils::SetMask<U>(mask);
        } else {
            AscendCUtils::SetMask<T>(mask);
        }
    }
    CastIntrinsicsImpl(dst, src, roundMode, repeatTime, repeatParams);
}

// CastDeq ccec intrinsics
template <typename T, bool halfBlock>
__aicore__ inline void CastDeqIntrinsicsImpl(__ubuf__ T* dst, __ubuf__ int16_t* src, uint8_t repeatTime,
    const UnaryRepeatParams& repeatParams)
{
    vconv_deqs162b8(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
        repeatParams.dstRepStride, repeatParams.srcRepStride, repeatParams.repeatStrideMode,
        repeatParams.strideSizeMode, halfBlock);
}
template <typename T, bool halfBlock>
__aicore__ inline void CastVDeqIntrinsicsImpl(__ubuf__ T* dst, __ubuf__ int16_t* src, uint8_t repeatTime,
    const UnaryRepeatParams& repeatParams)
{
    vconv_vdeqs162b8(dst, src, repeatTime, repeatParams.dstBlkStride, repeatParams.srcBlkStride,
        repeatParams.dstRepStride, repeatParams.srcRepStride, repeatParams.repeatStrideMode,
        repeatParams.strideSizeMode, halfBlock);
}

// CastDeq::Level 2
template <typename T, typename U, bool isVecDeq, bool halfBlock>
__aicore__ inline void CastDeqImpl(__ubuf__ T* dst, __ubuf__ U* src,
    const uint32_t count)
{
    ASCENDC_ASSERT((SupportType<T, int8_t, uint8_t>() && SupportType<U, int16_t>()),
        {KERNEL_LOG(KERNEL_ERROR, "Failed to check dtype in CastDeq, current api support dtype combination is dst: "
        "int8_t / uint8_t, src: int16_t");});
    set_mask_count();
    set_vector_mask(0, count);
    struct UnaryRepeatParams repeatParams;
    if constexpr (isVecDeq) {
        CastVDeqIntrinsicsImpl<T, halfBlock>(dst, src, 1, repeatParams);
    } else {
        CastDeqIntrinsicsImpl<T, halfBlock>(dst, src, 1, repeatParams);
    }
    set_mask_norm();
    set_vector_mask(static_cast<uint64_t>(-1), static_cast<uint64_t>(-1));
}

// CastDeq::Level 0 - mask bit mode
template <typename T, typename U, bool isSetMask, bool isVecDeq, bool halfBlock>
__aicore__ inline void CastDeqImpl(__ubuf__ T* dst, __ubuf__ U* src,
    const uint64_t mask[], uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    ASCENDC_ASSERT((SupportType<T, int8_t, uint8_t>() && SupportType<U, int16_t>()),
        {KERNEL_LOG(KERNEL_ERROR, "Failed to check dtype in CastDeq, current api support dtype combination is dst: "
        "int8_t / uint8_t, src: int16_t");});
    AscendCUtils::SetMask<U, isSetMask>(mask[1], mask[0]);
    if constexpr (isVecDeq) {
        CastVDeqIntrinsicsImpl<T, halfBlock>(dst, src, repeatTime, repeatParams);
    } else {
        CastDeqIntrinsicsImpl<T, halfBlock>(dst, src, repeatTime, repeatParams);
    }
}

// CastDeq::Level 0 - mask count mode
template <typename T, typename U, bool isSetMask, bool isVecDeq, bool halfBlock>
__aicore__ inline void CastDeqImpl(__ubuf__ T* dst, __ubuf__ U* src,
    const int32_t mask, uint8_t repeatTime, const UnaryRepeatParams& repeatParams)
{
    ASCENDC_ASSERT((SupportType<T, int8_t, uint8_t>() && SupportType<U, int16_t>()),
        {KERNEL_LOG(KERNEL_ERROR, "Failed to check dtype in CastDeq, current api support dtype combination is dst: "
        "int8_t / uint8_t, src: int16_t");});
    AscendCUtils::SetMask<U, isSetMask>(mask);
    if constexpr (isVecDeq) {
        CastVDeqIntrinsicsImpl<T, halfBlock>(dst, src, repeatTime, repeatParams);
    } else {
        CastDeqIntrinsicsImpl<T, halfBlock>(dst, src, repeatTime, repeatParams);
    }
}


template <typename T, typename U>
__aicore__ inline void AddReluCastIntrinsicsImpl(__ubuf__ T* dst, __ubuf__ U* src0, __ubuf__ U* src1, uint8_t repeatTime,
    const BinaryRepeatParams& repeatParams)
{
    static_assert(SupportType<Tuple<U, T>, Tuple<half, int8_t>, Tuple<float, half>, Tuple<int16_t, int8_t>>(),
        "Failed to check dtype in AddReluCast, current api support dtype combination is src: half, dst: int8_t; src: "
        "float, dst: half; src: int16_t, dst: int8_t.");
    if constexpr (SupportType<Tuple<U, T>, Tuple<half, int8_t>>()) {
        vaddreluconv_f162s8(dst, src0, src1, repeatTime, repeatParams.dstBlkStride, repeatParams.src0BlkStride,
            repeatParams.src1BlkStride, repeatParams.dstRepStride, repeatParams.src0RepStride,
            repeatParams.src1RepStride, 0, 0, false);
    } else if constexpr (SupportType<Tuple<U, T>, Tuple<float, half>>()) {
        vaddreluconv_f322f16(dst, src0, src1, repeatTime, repeatParams.dstBlkStride, repeatParams.src0BlkStride,
            repeatParams.src1BlkStride, repeatParams.dstRepStride, repeatParams.src0RepStride,
            repeatParams.src1RepStride, 0, 0, false);
    } else {
        vaddreluconv_s162s8(dst, src0, src1, repeatTime, repeatParams.dstBlkStride, repeatParams.src0BlkStride,
            repeatParams.src1BlkStride, repeatParams.dstRepStride, repeatParams.src0RepStride,
            repeatParams.src1RepStride, 0, 0, false);
    }
}

// AddReluCast::Level 0 - mask count mode
template <typename T, typename U, bool isSetMask = true>
__aicore__ inline void AddReluCastImpl(__ubuf__ T* dst, __ubuf__ U* src0, __ubuf__ U* src1,
    const uint64_t mask, uint8_t repeatTime, const BinaryRepeatParams& repeatParams)
{
    if constexpr (isSetMask) {
        if constexpr (sizeof(T) >= sizeof(U)) {
            AscendCUtils::SetMask<U>(mask);
        } else {
            AscendCUtils::SetMask<T>(mask);
        }
    }
    AddReluCastIntrinsicsImpl(dst, src0, src1, repeatTime, repeatParams);
}

// AddReluCast::Level 0 - mask bit mode
template <typename T, typename U, bool isSetMask = true>
__aicore__ inline void AddReluCastImpl(__ubuf__ T* dst, __ubuf__ U* src0, __ubuf__ U* src1,
    const uint64_t mask[], uint8_t repeatTime, const BinaryRepeatParams& repeatParams)
{
    if constexpr (isSetMask) {
        if constexpr (sizeof(T) >= sizeof(U)) {
            AscendCUtils::SetMask<U>(mask[1], mask[0]);
        } else {
            AscendCUtils::SetMask<T>(mask[1], mask[0]);
        }
    }
    AddReluCastIntrinsicsImpl(dst, src0, src1, repeatTime, repeatParams);
}

// AddReluCast::Level 2
template <typename T, typename U>
__aicore__ inline void AddReluCastImpl(__ubuf__ T* dst, __ubuf__ U* src0, __ubuf__ U* src1,
    const uint32_t count)
{
    set_mask_count();
    set_vector_mask(0, count);
    if constexpr (sizeof(T) > sizeof(U)) {
        AddReluCastIntrinsicsImpl(dst, src0, src1, 1, {1, 1, 1, DEFAULT_REPEAT_STRIDE,
            DEFAULT_REPEAT_STRIDE / HALF_FACTOR, DEFAULT_REPEAT_STRIDE / HALF_FACTOR});
    } else if constexpr (sizeof(T) < sizeof(U)) {
        AddReluCastIntrinsicsImpl(dst, src0, src1, 1, {1, 1, 1, DEFAULT_REPEAT_STRIDE / HALF_FACTOR,
            DEFAULT_REPEAT_STRIDE, DEFAULT_REPEAT_STRIDE});
    } else {
        AddReluCastIntrinsicsImpl(dst, src0, src1, 1, {1, 1, 1, DEFAULT_REPEAT_STRIDE, DEFAULT_REPEAT_STRIDE,
            DEFAULT_REPEAT_STRIDE});
    }
    set_mask_norm();
    set_vector_mask(static_cast<uint64_t>(-1), static_cast<uint64_t>(-1));
}

template <typename T, typename U>
__aicore__ inline void SubReluCastIntrinsicsImpl(__ubuf__ T* dst, __ubuf__ U* src0, __ubuf__ U* src1, uint8_t repeatTime,
    const BinaryRepeatParams& repeatParams)
{
    static_assert(SupportType<Tuple<U, T>, Tuple<half, int8_t>, Tuple<float, half>, Tuple<int16_t, int8_t>>(),
        "Failed to check dtype in SubReluCast, current api support dtype combination is src: half, dst: int8_t; src: "
        "float, dst: half; src: int16_t, dst: int8_t.");
    if constexpr (SupportType<Tuple<U, T>, Tuple<half, int8_t>>()) {
        vsubreluconv_f162s8(dst, src0, src1, repeatTime, repeatParams.dstBlkStride, repeatParams.src0BlkStride,
            repeatParams.src1BlkStride, repeatParams.dstRepStride, repeatParams.src0RepStride,
            repeatParams.src1RepStride, false, false, false);
    } else if constexpr (SupportType<Tuple<U, T>, Tuple<float, half>>()) {
        vsubreluconv_f322f16(dst, src0, src1, repeatTime, repeatParams.dstBlkStride, repeatParams.src0BlkStride,
            repeatParams.src1BlkStride, repeatParams.dstRepStride, repeatParams.src0RepStride,
            repeatParams.src1RepStride, false, false, false);
    } else {
        vsubreluconv_s162s8(dst, src0, src1, repeatTime, repeatParams.dstBlkStride, repeatParams.src0BlkStride,
            repeatParams.src1BlkStride, repeatParams.dstRepStride, repeatParams.src0RepStride,
            repeatParams.src1RepStride, false, false, false);
    }
}

// SubReluCast::Level 2
template <typename T, typename U>
__aicore__ inline void SubReluCastImpl(__ubuf__ T* dst, __ubuf__ U* src0, __ubuf__ U* src1,
    const uint32_t count)
{
    set_mask_count();
    set_vector_mask(0, count);
    if constexpr (sizeof(T) > sizeof(U)) {
        SubReluCastIntrinsicsImpl(dst, src0, src1, 1, {1, 1, 1, DEFAULT_REPEAT_STRIDE,
            DEFAULT_REPEAT_STRIDE / HALF_FACTOR, DEFAULT_REPEAT_STRIDE / HALF_FACTOR});
    } else if constexpr (sizeof(T) < sizeof(U)) {
        SubReluCastIntrinsicsImpl(dst, src0, src1, 1, {1, 1, 1, DEFAULT_REPEAT_STRIDE / HALF_FACTOR,
            DEFAULT_REPEAT_STRIDE, DEFAULT_REPEAT_STRIDE});
    } else {
        SubReluCastIntrinsicsImpl(dst, src0, src1, 1, {1, 1, 1, DEFAULT_REPEAT_STRIDE, DEFAULT_REPEAT_STRIDE,
            DEFAULT_REPEAT_STRIDE});
    }
    set_mask_norm();
    set_vector_mask(static_cast<uint64_t>(-1), static_cast<uint64_t>(-1));
}

// SubReluCast::Level 0 - mask count mode
template <typename T, typename U, bool isSetMask = true>
__aicore__ inline void SubReluCastImpl(__ubuf__ T* dst, __ubuf__ U* src0, __ubuf__ U* src1,
    const uint64_t mask, uint8_t repeatTime, const BinaryRepeatParams& repeatParams)
{
    if constexpr (isSetMask) {
        if constexpr (sizeof(T) >= sizeof(U)) {
            AscendCUtils::SetMask<U>(mask);
        } else {
            AscendCUtils::SetMask<T>(mask);
        }
    }
    SubReluCastIntrinsicsImpl(dst, src0, src1, repeatTime, repeatParams);
}

// SubReluCast::Level 0 - mask bit mode
template <typename T, typename U, bool isSetMask = true>
__aicore__ inline void SubReluCastImpl(__ubuf__ T* dst, __ubuf__ U* src0, __ubuf__ U* src1,
    const uint64_t mask[], uint8_t repeatTime, const BinaryRepeatParams& repeatParams)
{
    if constexpr (isSetMask) {
        if constexpr (sizeof(T) >= sizeof(U)) {
            AscendCUtils::SetMask<U>(mask[1], mask[0]);
        } else {
            AscendCUtils::SetMask<T>(mask[1], mask[0]);
        }
    }
    SubReluCastIntrinsicsImpl(dst, src0, src1, repeatTime, repeatParams);
}

__aicore__ inline uint64_t MakeDeqScaleConfig(float scale, int16_t offset, bool signMode)
{
    constexpr uint64_t signModeBit = 46;
    constexpr uint64_t offsetMask = 0x1ff;
    constexpr uint64_t offsetBit = 37;
    uint64_t config = ((static_cast<uint64_t>(signMode) << signModeBit) | ((offset & offsetMask) << offsetBit) |
                       *(reinterpret_cast<uint32_t *>(&scale)));
    return config;
}

__aicore__ inline void SetDeqScaleImpl(float scale, int16_t offset, bool signMode)
{
    set_deqscale(MakeDeqScaleConfig(scale, offset, signMode));
}

template <typename T>
__aicore__ inline void SetDeqScaleImpl(const LocalTensor<T>& vdeq, const VdeqInfo& vdeqInfo)
{
    for (uint8_t i = 0; i < VDEQ_TENSOR_SIZE; i++) {
        float scale = vdeqInfo.vdeqScale[i];
        int16_t offset = vdeqInfo.vdeqOffset[i];
        bool signMode = vdeqInfo.vdeqSignMode[i];
        vdeq.SetValue(i, static_cast<T>(MakeDeqScaleConfig(scale, offset, signMode)));
    }
#if ASCENDC_CPU_DEBUG
    set_deqscale((uint64_t)vdeq.GetPhyAddr());
#else
    constexpr uint64_t deqAddr = 5; // 32B align
    set_deqscale(((uint64_t)vdeq.GetPhyAddr()) >> deqAddr);
#endif
}

template<typename T>
__aicore__ inline void SetDeqScaleImpl(T config)
{
    set_deqscale(config);
}
} // namespace AscendC
#endif // ASCENDC_MODULE_OPERATOR_VEC_VCONV_IMPL_H
